home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / sokoban-.tar / sokoban-src.tar / sokoban / play.c < prev    next >
C/C++ Source or Header  |  1992-05-16  |  8KB  |  259 lines

  1. #include <ctype.h>
  2. #include <curses.h>
  3. #include "sokoban.h"
  4.  
  5. /* defining the types of move */
  6. #define MOVE         1
  7. #define PUSH         2
  8. #define SAVE         3
  9. #define UNSAVE         4
  10. #define STOREMOVE     5
  11. #define STOREPUSH     6
  12.  
  13. /* defines for control characters */
  14. #define CNTL_L        '\014'
  15. #define CNTL_K        '\013'
  16. #define CNTL_H        '\010'
  17. #define CNTL_J        '\012'
  18. #define CNTL_R        '\022'
  19. #define CNTL_U        '\025'
  20.  
  21. extern char  map[MAXROW+1][MAXCOL+1];
  22. extern short rows, cols, level, moves, pushes, savepack, packets;
  23. extern short scorelevel, scoremoves, scorepushes;
  24. extern POS   ppos;
  25.  
  26. static POS   tpos1,           /* testpos1: 1 pos. over/under/left/right */
  27.              tpos2,           /* testpos2: 2 pos.  "                    */
  28.              lastppos,           /* the last player position (for undo)    */
  29.              last_p1, last_p2; /* last test positions (for undo)         */
  30. static char lppc, ltp1c, ltp2c;    /* the char for the above pos. (for undo) */
  31. static short action, lastaction;
  32.  
  33. /** For the temporary save **/
  34. static char  tmp_map[MAXROW+1][MAXCOL+1];
  35. static short tmp_pushes, tmp_moves, tmp_savepack;
  36. static POS   tmp_ppos;
  37.  
  38. short play() {
  39.  
  40.    short c;
  41.    short ret;
  42.    short undolock = 1;        /* locked for undo */
  43.  
  44.    showscreen();
  45.    tmpsave();
  46.    ret = 0;
  47.    while( ret == 0) {
  48.       (void) read(0, &c, 1);
  49.       switch(c) { case '8': c = 'k'; break;
  50.                   case '2': c = 'j'; break;
  51.                   case '4': c = 'h'; break;
  52.           case '6': c = 'l'; break;
  53.           case '5': c = 'u'; break;
  54.                   case '\x1B':
  55.                  (void) read(0, &c, 1);
  56.                              if(c == '[')
  57.                                 {  (void) read(0, &c, 1);    
  58.                    switch(c)
  59.                                      {  case 'A': c = 'k'; break;      
  60.                         case 'B': c = 'j'; break;
  61.                     case 'D': c = 'h'; break;
  62.                     case 'C': c = 'l'; break; 
  63.                     default:  c = 'z'; break;};};                 
  64.  
  65.                   default: break; };
  66.  
  67.       switch(c) {
  68.      case 'q':    /* quit the game                     */
  69.                   ret = E_ENDGAME; 
  70.                   break;
  71.      case 's':    /* save the games                    */
  72.               if( (ret = savegame()) == 0)
  73.              ret = E_SAVED;
  74.               break;
  75.      case '?':    /* show the help file                */
  76.               showhelp();
  77.               showscreen();
  78.               break;
  79.      case CNTL_R: /* refresh the screen                 */
  80.               clear();
  81.               showscreen();
  82.               break;
  83.      case 'c':    /* temporary save                    */
  84.               tmpsave();
  85.               break;
  86.      case CNTL_U: /* reset to temporary save             */
  87.               tmpreset();
  88.               undolock = 1;
  89.               showscreen();
  90.               break;
  91.      case 'U':    /* undo this level                 */
  92.               moves = pushes = 0;
  93.               if( (ret = readscreen()) == 0) {
  94.                  showscreen();
  95.              undolock = 1;
  96.               }
  97.               break;
  98.      case 'u':    /* undo last move                 */
  99.               if( ! undolock) {
  100.                  undomove();
  101.                  undolock = 1;
  102.               }
  103.               break;
  104.  
  105.          case 'k':    /* up                         */
  106.      case 'K':    /* run up                     */
  107.      case CNTL_K: /* run up, stop before object             */
  108.      case 'j':    /* down                         */
  109.      case 'J':    /* run down                     */
  110.      case CNTL_J: /* run down, stop before object             */
  111.      case 'l':    /* right                         */
  112.      case 'L':    /* run right                     */
  113.      case CNTL_L: /* run right, stop before object             */
  114.      case 'h':    /* left                         */
  115.      case 'H':    /* run left                     */
  116.      case CNTL_H: /* run left, stop before object             */
  117.               do {
  118.                  if( (action = testmove( c)) != 0) {
  119.                 lastaction = action;
  120.                     lastppos.x = ppos.x; lastppos.y = ppos.y;
  121.                     lppc = map[ppos.x][ppos.y];
  122.                     last_p1.x = tpos1.x; last_p1.y = tpos1.y; 
  123.                     ltp1c = map[tpos1.x][tpos1.y];
  124.                     last_p2.x = tpos2.x; last_p2.y = tpos2.y; 
  125.                     ltp2c = map[tpos2.x][tpos2.y];
  126.                     domove( lastaction); 
  127.                     undolock = 0;
  128.                  }
  129.               } while( (action != 0) && (! islower( c))
  130.                   && (packets != savepack));
  131.               break;
  132.      default:     helpmessage(); break;
  133.       }
  134.       if( (ret == 0) && (packets == savepack)) {
  135.      scorelevel = level;
  136.      scoremoves = moves;
  137.      scorepushes = pushes;
  138.      break;
  139.       }
  140.    }
  141.    return( ret);
  142. }
  143.  
  144. testmove( action)
  145. register short action;
  146. {
  147.    register short ret;
  148.    register char  tc;
  149.    register short stop_at_object;
  150.  
  151.    if( (stop_at_object = iscntrl( action))) action = action + 'A' - 1;
  152.    action = (isupper( action)) ? tolower( action) : action;
  153.    if( (action == 'k') || (action == 'j')) {
  154.       tpos1.x = (action == 'k') ? ppos.x-1 : ppos.x+1;
  155.       tpos2.x = (action == 'k') ? ppos.x-2 : ppos.x+2;
  156.       tpos1.y = tpos2.y = ppos.y;
  157.    }
  158.    else {
  159.       tpos1.y = (action == 'h') ? ppos.y-1 : ppos.y+1;
  160.       tpos2.y = (action == 'h') ? ppos.y-2 : ppos.y+2;
  161.       tpos1.x = tpos2.x = ppos.x;
  162.    }
  163.    tc = map[tpos1.x][tpos1.y];
  164.    if( (tc == packet.obj_intern) || (tc == save.obj_intern)) {
  165.       if( ! stop_at_object) {
  166.          if( map[tpos2.x][tpos2.y] == ground.obj_intern)
  167.             ret = (tc == save.obj_intern) ? UNSAVE : PUSH;
  168.          else if( map[tpos2.x][tpos2.y] == store.obj_intern)
  169.             ret = (tc == save.obj_intern) ? STOREPUSH : SAVE;
  170.          else ret = 0;
  171.       }
  172.       else ret = 0;
  173.    }
  174.    else if( tc == ground.obj_intern)
  175.       ret = MOVE;
  176.    else if( tc == store.obj_intern)
  177.       ret = STOREMOVE;
  178.    else ret = 0;
  179.    return( ret);
  180. }
  181.  
  182. domove( moveaction) 
  183. register short moveaction;
  184. {
  185.    map[ppos.x][ppos.y] = (map[ppos.x][ppos.y] == player.obj_intern) 
  186.                    ? ground.obj_intern 
  187.                    : store.obj_intern;
  188.    switch( moveaction) {
  189.       case MOVE:      map[tpos1.x][tpos1.y] = player.obj_intern;     break;
  190.       case STOREMOVE: map[tpos1.x][tpos1.y] = playerstore.obj_intern;     break;
  191.       case PUSH:      map[tpos2.x][tpos2.y] = map[tpos1.x][tpos1.y];
  192.               map[tpos1.x][tpos1.y] = player.obj_intern;    
  193.               pushes++;                        break;
  194.       case UNSAVE:    map[tpos2.x][tpos2.y] = packet.obj_intern;
  195.               map[tpos1.x][tpos1.y] = playerstore.obj_intern;        
  196.               pushes++; savepack--;                 break;
  197.       case SAVE:      map[tpos2.x][tpos2.y] = save.obj_intern;
  198.               map[tpos1.x][tpos1.y] = player.obj_intern;            
  199.               savepack++; pushes++;                break;
  200.       case STOREPUSH: map[tpos2.x][tpos2.y] = save.obj_intern;
  201.               map[tpos1.x][tpos1.y] = playerstore.obj_intern;        
  202.               pushes++;                        break;
  203.    }
  204.    moves++;
  205.    dispmoves(); disppushes(); dispsave();
  206.    mapchar( map[ppos.x][ppos.y], ppos.x, ppos.y);
  207.    mapchar( map[tpos1.x][tpos1.y], tpos1.x, tpos1.y);
  208.    mapchar( map[tpos2.x][tpos2.y], tpos2.x, tpos2.y);
  209.    move( MAXROW+1, 0);
  210.    refresh();
  211.    ppos.x = tpos1.x; ppos.y = tpos1.y;
  212. }
  213.  
  214. undomove() {
  215.  
  216.    map[lastppos.x][lastppos.y] = lppc;
  217.    map[last_p1.x][last_p1.y] = ltp1c;
  218.    map[last_p2.x][last_p2.y] = ltp2c;
  219.    ppos.x = lastppos.x; ppos.y = lastppos.y;
  220.    switch( lastaction) {
  221.       case MOVE:      moves--;                break;
  222.       case STOREMOVE: moves--;                break;
  223.       case PUSH:      moves--; pushes--;        break;
  224.       case UNSAVE:    moves--; pushes--; savepack++;    break;
  225.       case SAVE:      moves--; pushes--; savepack--;    break;
  226.       case STOREPUSH: moves--; pushes--;        break;
  227.    }
  228.    dispmoves(); disppushes(); dispsave();
  229.    mapchar( map[ppos.x][ppos.y], ppos.x, ppos.y);
  230.    mapchar( map[last_p1.x][last_p1.y], last_p1.x, last_p1.y);
  231.    mapchar( map[last_p2.x][last_p2.y], last_p2.x, last_p2.y);
  232.    move( MAXROW+1, 0);
  233.    refresh();
  234. }
  235.  
  236. tmpsave() {
  237.  
  238.    register short i, j;
  239.  
  240.    for( i = 0; i < rows; i++) for( j = 0; j < cols; j++)
  241.       tmp_map[i][j] = map[i][j];
  242.    tmp_pushes = pushes;
  243.    tmp_moves = moves;
  244.    tmp_savepack = savepack;
  245.    tmp_ppos.x = ppos.x; tmp_ppos.y = ppos.y;
  246. }
  247.  
  248. tmpreset() {
  249.  
  250.    register short i, j;
  251.  
  252.    for( i = 0; i < rows; i++) for( j = 0; j < cols; j++)
  253.       map[i][j] = tmp_map[i][j];
  254.    pushes = tmp_pushes;
  255.    moves = tmp_moves;
  256.    savepack = tmp_savepack;
  257.    ppos.x = tmp_ppos.x; ppos.y = tmp_ppos.y;
  258. }
  259.